/**      
 * @file		appending.cpp
 * @description		Demonstrates appending data to a file.
 *			If the file exists and has data, we want
 *			to save the existing data and add to it.
 *			If we don't use the ios::app flag, the 
 *			open function will erase the contents of
 *			the file.
 * @course		CSCI 123 Section 00000
 * @assignment 
 * @date		mm/dd/yyyy
 * @author		Brad Rippe (00000000) brippe@fullcoll.edu
 * @version		1.0
 */
#include <fstream>
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;

/* Declare the file names as global constants */
const string INPUT_FILE_1	= "input1.txt";
const string INPUT_FILE_2	= "input2.txt";
const string INPUT_FILE_3	= "input3.txt";
const string INPUT_FILE_4	= "input4.txt";
const string OUTPUT_FILE	= "appended.txt";

/**
 * Opens the file for input and checks for failure
 * @param	aInFile the file input
 * @param	aFileName the name of the file to open
 * @pre		the input stream and the filename have been
 *		been initialized to values
 * @post	the file has been opened or the application
 *		is terminated
 */
void openFile(ifstream& aInFile, const string& aFileName);

/**
 * Opens the file for output and checks for failure
 * @param	aOutFile the file output file
 * @param	aFileName the name of the file to open
 * @param	aCreate create the file for output, if the file exists
 *		the file will be recreated erasing the data in the file
 *		if false the data is appended to the file
 * @pre		the output stream and the filename have been
 *		been initialized to values
 * @post	the file has been opened and is ready to receive data or
 *		the application is terminated
 */
void openFile(ofstream& aOutFiles, const string& aFileName, bool aCreate);

/**
 * The input file is read from and the contents written to the 
 * output file
 * @param	aInFile the file input
 * @param	aFileName the name of the file to open
 * @pre		the input stream and the filename have been
 *		been initialized to values
 * @post	the file has been opened or the application
 *		is terminated
 */
void readAndWrite(ifstream& aInFile, ofstream& aOutFile);

/**
 * Close the input and output files
 * @param	aInFile the file input
 * @param	aOutFile the output file
 * @pre		the input and output files have been opened
 * @post	the input and output files have been closed 
 */
void closeFiles(ifstream& aInFile, ofstream& aOutFile);

/**
 * @return zero if the application executes successfully
 */
int main() {
	ifstream inFiles;	// we don't have to declare four
				// objects of type ifstream to read
				// from four different files
				// we can reuse one variable
	ofstream outFile;

	bool createFile = true;
	string inputFile = INPUT_FILE_1;

	for(int i = 0; i < 4; i++) {
		if(i == 1) {
			inputFile = INPUT_FILE_2;
			createFile = false;
		} else if(i == 2) {
			inputFile = INPUT_FILE_3;
			createFile = false;
		} else if(i == 3) {
			inputFile = INPUT_FILE_4;
			createFile = false;
		}
		openFile(inFiles, inputFile);
		openFile(outFile, OUTPUT_FILE, createFile);
		cout << "Writing " << OUTPUT_FILE << endl;
		cout << "Output from " << inputFile << endl;
		readAndWrite(inFiles, outFile);
		closeFiles(inFiles, outFile);
	}

	return 0;
}

void openFile(ifstream& aInFile, const string& aFileName) {
	aInFile.open(aFileName.c_str());	
	if(aInFile.fail()) {
		cout << "Couldn't open input file!\n";
		exit(1);
	}
}

void openFile(ofstream& aOutFile, const string& aFileName, bool aCreate) {
	// if aCreate is set to true
	// we'll create the file or erase what's there
	// otherwise we'll append the file
	if(aCreate) {
		//the c_str() is a member function of the 
		//string class. it converts the string to
		//a cstring. 
		cout << "Creating " << aFileName << endl;
		aOutFile.open(aFileName.c_str());
	} else {
		cout << "Appending " << aFileName << endl;
		aOutFile.open(aFileName.c_str(), ios::app);
	}
	if(aOutFile.fail()) {
		cout << "Couldn't open output file!\n";
		exit(1);
	}
}

void readAndWrite(ifstream& aInFile, ofstream& aOutFile) {
	// remember the extraction operator skips
	// blank spaces to find the next word
	// so we have to output blanks in the new output
	// file.
	string word;
	while(aInFile >> word) {
		aOutFile << word << " ";
	}
	aOutFile << "\n\n";
}

void closeFiles(ifstream& aInFile, ofstream& aOutFile) {
	aInFile.close();
	aInFile.clear();	// clear all error flags
	aOutFile.close();	
	aOutFile.clear();	// this resets any flags set by a 
				// previous read or write
}
